package com.zkh.myutils.bean;

import com.zkh.myutils.utils.DateUtils;
import com.zkh.myutils.utils.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 整体类型转换
 */
public class WholeTypeConverter {

	/**
	 * 数字整体类型
	 */
	public static final List<String> TYPE_NUMBER_LIST = Arrays.asList(
		Type.BASE_BYTE, Type.BASE_SHORT, Type.BASE_INT, Type.BASE_LONG, Type.BASE_FLOAT, Type.BASE_DOUBLE, Type.BIGINTEGER, Type.BIGDECIMAL,
		Type.BYTE, Type.SHORT, Type.INTEGER, Type.LONG, Type.FLOAT, Type.DOUBLE
	);

	/**
	 * 所有整体类型
	 */
	public static final List<String> TYPE_WHOLE_LIST = Arrays.asList(
		Type.BASE_BYTE, Type.BYTE, Type.BASE_SHORT, Type.SHORT, Type.BASE_INT, Type.INTEGER, Type.BASE_LONG, Type.LONG, Type.BASE_FLOAT, Type.FLOAT, Type.BASE_DOUBLE, Type.DOUBLE, Type.BASE_BOOL, Type.BOOL,
		Type.BASE_CHAR, Type.CHARACTER, Type.BIGINTEGER, Type.BIGDECIMAL, Type.DATE,Type.STRING, Type.DATE, Type.TIMESTAMP
	);

	/**
	 * 转换整体类型
	 * @param obj 待转换的值
	 * @param fromType 原类型
	 * @param toType 目标类型
	 * @return 转换后的值
	 */
	public static Object cast(Object obj, Class<?> fromType, Class<?> toType){
		return cast(obj, fromType.getName(), toType.getName());
	}

	/**
	 * 转换整体类型
	 * @param obj 待转换的值
	 * @param fromType 原类型
	 * @param toType 目标类型
	 * @return 转换后的值
	 */
	public static Object cast(Object obj, String fromType, String toType){
		return cast(obj, fromType, toType, null);
	}

	/**
	 * 转换整体类型
	 * @param obj 待转换的值
	 * @param fromType 原类型
	 * @param toType 目标类型
	 * @return 转换后的值
	 */
	public static Object cast(Object obj, Class<?> fromType, Class<?> toType, String dateFormat){
		return cast(obj, fromType.getName(), toType.getName(), dateFormat);
	}

	/**
	 * 转换整体类型
	 * @param obj 待转换的值
	 * @param fromType 原类型
	 * @param toType 目标类型
	 * @return 转换后的值
	 */
	public static Object cast(Object obj, String fromType, String toType, String dateFormat){
		//为空
		if(obj==null){
			return null;
		}
		//目标为字符串
		if(Type.STRING.equals(toType)){
			//从Date转换
			if(StringUtils.isExist(fromType, Type.DATE, Type.TIMESTAMP) && dateFormat!=null){
				return DateUtils.getString((Date) obj, dateFormat);
			}
			return obj.toString();
		}
		//类型相同
		if(fromType.equals(toType)){
			return obj;
		}
		//按类型转换
		switch (fromType){
			case Type.BASE_BYTE:
			case Type.BYTE:
			case Type.BASE_SHORT:
			case Type.SHORT:
			case Type.BASE_INT:
			case Type.INTEGER:
			case Type.BASE_LONG:
			case Type.LONG:
			case Type.BASE_FLOAT:
			case Type.FLOAT:
			case Type.BASE_DOUBLE:
			case Type.DOUBLE:
			case Type.BIGINTEGER:
			case Type.BIGDECIMAL:
				//目标类型
				switch (toType){
					case Type.BASE_BYTE:
					case Type.BYTE:
						return ((Number) obj).byteValue();
					case Type.BASE_SHORT:
					case Type.SHORT:
						return ((Number) obj).shortValue();
					case Type.BASE_INT:
					case Type.INTEGER:
						return ((Number) obj).intValue();
					case Type.BASE_LONG:
					case Type.LONG:
						return ((Number) obj).longValue();
					case Type.BASE_FLOAT:
					case Type.FLOAT:
						return ((Number) obj).floatValue();
					case Type.BASE_DOUBLE:
					case Type.DOUBLE:
						return ((Number) obj).doubleValue();
					case Type.BIGINTEGER:
						return new BigInteger(obj.toString());
					case Type.BIGDECIMAL:
						return new BigDecimal(obj.toString());
					case Type.BASE_BOOL:
					case Type.BOOL:
						return Double.compare(0.0, ((Number) obj).doubleValue()) !=0;
					case Type.BASE_CHAR:
					case Type.CHARACTER:
						return obj.toString().charAt(0);
					default:
						throw new IllegalArgumentException(fromType + "不能转换为" + toType);
				}
			case Type.BASE_BOOL:
				if(Type.BOOL.equals(toType)){
					return obj;
				}
				throw new IllegalArgumentException(fromType + "不能转换为" + toType);
			case Type.BOOL:
				if(Type.BASE_BOOL.equals(toType)){
					return obj;
				}
				throw new IllegalArgumentException(fromType + "不能转换为" + toType);
			case Type.DATE:
				if(Type.TIMESTAMP.equals(toType)){
					return new Timestamp(((Date) obj).getTime());
				}
				//boolean类型和Date类型不能转换
				throw new IllegalArgumentException(fromType + "不能转换为" + toType);
			case Type.TIMESTAMP:
				if(Type.DATE.equals(toType)){
					return new Date(((Timestamp) obj).getTime());
				}
				//boolean类型和Date类型不能转换
				throw new IllegalArgumentException(fromType + "不能转换为" + toType);
			case Type.BASE_CHAR:
			case Type.CHARACTER:
				//目标类型
				switch (toType){
					case Type.BASE_BYTE:
					case Type.BYTE:
						return Byte.parseByte(obj + "");
					case Type.BASE_SHORT:
					case Type.SHORT:
						return Short.parseShort(obj + "");
					case Type.BASE_INT:
					case Type.INTEGER:
						return Integer.parseInt(obj + "");
					case Type.BASE_LONG:
					case Type.LONG:
						return Long.parseLong(obj + "");
					case Type.BASE_FLOAT:
					case Type.FLOAT:
						return Float.parseFloat(obj + "");
					case Type.BASE_DOUBLE:
					case Type.DOUBLE:
						return Double.parseDouble(obj + "");
					case Type.BIGINTEGER:
						return new BigInteger(obj + "");
					case Type.BIGDECIMAL:
						return new BigDecimal(obj + "");
					case Type.BASE_BOOL:
					case Type.BOOL:
						return ((char) obj)!='\0';
					case Type.BASE_CHAR:
					case Type.CHARACTER:
						return obj;
					default:
						throw new IllegalArgumentException(fromType + "不能转换为" + toType);
				}
			case Type.STRING:
				//转Date
				boolean toDate = false;
				//目标类型
				switch (toType){
					case Type.BASE_BYTE:
					case Type.BYTE:
						return Byte.parseByte(obj.toString());
					case Type.BASE_SHORT:
					case Type.SHORT:
						return Short.parseShort(obj.toString());
					case Type.BASE_INT:
					case Type.INTEGER:
						return Integer.parseInt(obj.toString());
					case Type.BASE_LONG:
					case Type.LONG:
						return Long.parseLong(obj.toString());
					case Type.BASE_FLOAT:
					case Type.FLOAT:
						return Float.parseFloat(obj.toString());
					case Type.BASE_DOUBLE:
					case Type.DOUBLE:
						return Double.parseDouble(obj.toString());
					case Type.BIGINTEGER:
						return new BigInteger(obj.toString());
					case Type.BIGDECIMAL:
						return new BigDecimal(obj.toString());
					case Type.BASE_BOOL:
					case Type.BOOL:
						return "true".equals(obj.toString());
					case Type.BASE_CHAR:
					case Type.CHARACTER:
						return obj.toString().charAt(0);
					case Type.DATE:
						toDate = true;
					case Type.TIMESTAMP:
						//日期结果
						Date result;
						//指定格式
						if(dateFormat!=null){
							result = DateUtils.getDate(obj.toString(), dateFormat);
						}else{
							try {
								result = DateUtils.getDate(obj.toString(), "yyyy-MM-dd");
							}catch(Exception e1){
								try {
									result = DateUtils.getDate(obj.toString(), "yyyy-MM-dd HH:mm:ss");
								}catch (Exception e2){
									throw new RuntimeException("字符串转" + toType + "失败：" + obj + "，默认支持标准的yyyy-MM-dd和yyyy-MM-dd HH:mm:ss格式");
								}
							}
						}
						return toDate ? result : new Timestamp(result.getTime());
				}
			default:
				throw new IllegalArgumentException("无法识别的整体类型：" + fromType);
		}
	}
}
